/**
 * 作者: 涛涛涛
 * 创建时间: 2021-06-03 10:00:34
 * @ 职责链.
 * @ 设置职责处理函数.
 * @ 然后调用exe
 */
type DutyFun<Param = any, Result = any> = (
    params: Param,
    resolve: (params?: Result) => void,
    next: (() => any) | undefined
) => any;
/** 条件:支持boolean值和函数返回boolean */
type Condition = boolean | ((par?: any) => boolean);

export class DutyChain<Param = any, Result = any> {
    constructor(dutyArr: DutyFun<Param, Result>[] = []) {
        this._dutyArr = dutyArr;
    }

    /** 职责链执行条件判断
     *  支持传入单个条件,或是传入条件数组.
     */
    public static executeConditions(..._params: Condition[]): boolean;
    public static executeConditions(..._params: [Condition[]]): boolean;
    public static executeConditions(..._params: Condition[] | [Condition[]]) {
        if (_params[0] === undefined) return true;
        let params: Condition[];
        if (Object.prototype.toString.call(_params[0]) === '[object Array]') params = _params[0] as Condition[];
        else params = _params as Condition[];
        let flag = true;
        for (let index = 0; index < params.length; index++) {
            let condition: Condition = params[index];
            if (typeof condition === 'function') condition = condition();
            if (!condition) {
                flag = false;
                break;
            }
        }
        return flag;
    }

    /** //公 添加职责函数*/
    public use(dutyFun: DutyFun<Param, Result>) {
        this._dutyArr.push(dutyFun);
    }
    /** //公 开始职责链运算(promise,异步变同步执行)
     * 顺序执行,当给出返回值的时候,就会停止执行后面的函数
     */
    public async exePromise(params: Param) {
        return await new Promise((resolve: (params?: Result) => void) => {
            this.__exe__(params, 0, resolve);
        });
    }

    /** //公 职责链运算(普通,同步执行)
     * 普通的js执行完所有的函数,如果方法中包含有异步函数,会有可能拿不到返回值.
     */
    public exeNormal(params: Param): Result {
        let result: Result = null;
        let resolve: (params?: Result) => void = (params) => {
            result = params;
        };
        this.__exe__(params, 0, resolve);
        return result;
    }
    /** //私 处理环境参数的数组 */
    private _dutyArr: DutyFun<Param, Result>[] = [];
    /** //私 递归处理职责 */
    private __exe__(params: Param, index: number, resolve: (params?: Result) => void) {
        if (!this._dutyArr[index]) return resolve(null);
        return this._dutyArr[index](params, resolve, () => {
            return this.__exe__(params, index + 1, resolve);
        });
    }
}
